
var FIXED_UPDATES_IN_A_SECOND = 1000/FIXED_STEP_IDEAL_DURATION_MS;

/**
 * @constructor
 */
function GameEntity(startX, startY, width, height, imgs, simulateUpdateStateDelay, simulateUpdateGraphicsDelay, name) {
	
	this.startX = startX;
	this.startY = startY;
	this.width = width;
	this.height = height;
	
	this.simulateUpdateStateDelay = simulateUpdateStateDelay;
	this.simulateUpdateGraphicsDelay = simulateUpdateGraphicsDelay;
	
	this.name = name;
	
	this.accumulatedTimeMs = 0;
	this.currentAnimationImageIdx = 0;
	
	this.imgs = imgs;
	
	this.loopsSinceLastImageIdxChanged = 0;
	
	this.debugStartTime = new Date().getTime();
	this.debugUpdatesCount = 0;
	this.debugConsole = new DebugConsole("debugConsole");
	
	/**
	 * @public
	 */
	this.processInput = function() {};
	
	/**
	 * @public
	 */
	this.updateState = function() {
		this.loopsSinceLastImageIdxChanged++;
		if(this.loopsSinceLastImageIdxChanged==FIXED_UPDATES_IN_A_SECOND) {
			this.currentAnimationImageIdx++;
            this.currentAnimationImageIdx = this.currentAnimationImageIdx%10;//wrap animation around            
            this.loopsSinceLastImageIdxChanged=0;
        }
		this.debugUpdatesCount++;
		this.debugPrecision();
	};
	
	/**
	 * @public
	 * @param{Context} canvas
	 */
	this.updateGraphics = function(context) {
		
		if(this.simulateUpdateGraphicsDelay && this.currentAnimationImageIdx==7) {
			var st = new Date().getTime();
			while(new Date().getTime()-st < 100) {}
		}
		context.drawImage(this.imgs[this.currentAnimationImageIdx], this.startX-this.width/2, this.startY-this.height/2, this.width, this.height);
	};
	
	/**
	 * @private
	 */
	this.debugPrecision = function() {	
		if(this.debugUpdatesCount%(5*FIXED_UPDATES_IN_A_SECOND)==0) {
			var curTime = new Date().getTime();
			var gameTimeMs = this.debugUpdatesCount * FIXED_STEP_IDEAL_DURATION_MS;
			var realTimeMs = new Date().getTime()-this.debugStartTime;
			var precision = (Math.min(gameTimeMs, realTimeMs)/Math.max(gameTimeMs, realTimeMs))*100;
			this.debugConsole.toConsole(this.name+" precision is: "+precision+" %");
		}		
	};
	
};


/**
 * @constructor
 */
function InputAwareGameEntity(startX, startY, width, height, imgs, simulateUpdateStateDelay, simulateUpdateGraphicsDelay, name) {

	$.extend(this,new GameEntity(startX, startY, width, height, imgs, simulateUpdateStateDelay, simulateUpdateGraphicsDelay, name));
	
	this.currentX = startX;
	this.currentY = startY;
	
	this.destinationX = startX;
	this.destinationY = startY;
	
	this.speed = 2;
	
	this.processInput = function(inputEvent) {
		this.destinationX = inputEvent.x;
		this.destinationY = inputEvent.y;
	};
	
	this.superUpdateState = this.updateState;	
	this.updateState = function() {
		this.superUpdateState();
		
		if(this.destinationX != this.currentX) {
			if(Math.abs(this.destinationX - this.currentX) < this.speed) {
				this.currentX = this.destinationX;
			} else {
				if(this.currentX>this.destinationX) {
					this.currentX -= this.speed;
				} else {
					this.currentX += this.speed;
				}
			}
		}
		
		if(this.destinationY != this.currentY) {
			if(Math.abs(this.destinationY - this.currentY) < this.speed) {
				this.currentY = this.destinationY;
			} else {
				if(this.currentY>this.destinationY) {
					this.currentY -= this.speed;
				} else {
					this.currentY += this.speed;
				}
			}
		}
		
	};
	
	this.updateGraphics = function(context) {
		context.drawImage(this.imgs[this.currentAnimationImageIdx], this.currentX-this.width/2, this.currentY-this.height/2, this.width, this.height);
	};
}
